package com.sky.wsp.camel;

import cn.hutool.core.io.file.FileReader;
import cn.hutool.core.io.file.FileWriter;
import cn.hutool.core.io.file.PathUtil;

import java.io.File;
import java.io.FileFilter;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.List;
import java.util.regex.Pattern;

/**
 * @desccription 针对JavaBean属性、getr/set方法，实现snake风格转换为camel风格
 * @auth wangshaopeng@talkweb.com.cn
 * @date 2022/12/20
 */
public class SnakeToCamelUtils {

    /**
     * TODO 1、要处理的文件，例如.java、.xml、.ts、.tsx、.vue等，每次只能处理一种文件。
     */
    private static String FILE_PATTEN = ".tsx";
    /**
     * TODO 2、匹配所有带下划线的变量、get、set方法等
     */
    private static Pattern WORD_PATTERN = Pattern.compile("_[a-z]+", Pattern.DOTALL);
    /**
     * TODO 3、要处理的项目目录。
     */
    private static String sourcePath = "D:\\workspace\\wutong-ui\\";
    /**
     * TODO 4、处理后的文件存放目录，因为直接修改文件太过危险，因此修改后的文件不会覆盖原有文件，而是新拷贝一份，然后用Beyond Compare等工具进行对比修改。
     */
    private static String targetPath = "D:\\table\\wutong-ui\\";
    private static Integer count = 0;

    public static void main(String[] args) {
        System.out.println("开始处理...");
        SnakeToCamelUtils.read();
    }

    public static void read() {
        Path path = Paths.get(sourcePath);
        boolean exists = PathUtil.exists(path, false);
        if (!exists) {
            System.err.println("指定路径不存在：" + sourcePath);
            return;
        }
        FileFilter filter = new JavaFileFilter();
        loopFiles(path, -1, filter);
        Log.log("");
        Log.log("================总共处理" + count + "个【" + FILE_PATTEN + "】文件!!!=======================");
        Log.persist(targetPath + "log.txt");

        System.out.println("================总共处理" + count + "个【" + FILE_PATTEN + "】文件!!!=======================");
        System.out.println("日志：" + targetPath + "log.txt");
    }

    public static void loopFiles(Path path, int maxDepth, FileFilter fileFilter) {
        if (null == path || false == Files.exists(path)) {
            return;
        }

        if (false == PathUtil.isDirectory(path)) {
            final File file = path.toFile();
            if (null == fileFilter || fileFilter.accept(file)) {
                parseFile(file);
            }
            return;
        }
        PathUtil.walkFiles(path, maxDepth, new SimpleFileVisitor<Path>() {

            @Override
            public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) {
                final File file = path.toFile();
                if (null == fileFilter || fileFilter.accept(file)) {
                    parseFile(file);
                }
                return FileVisitResult.CONTINUE;
            }
        });
    }

    public static void parseFile(File file) {
        StringBuilder sb = new StringBuilder();
        FileReader fileReader = new FileReader(file);
        List<String> lines = fileReader.readLines();
        if (lines.isEmpty()) {
            return;
        }
        Log.log("");
        Log.log(file.getPath());
        for (String l : lines) {
            String[] words = l.trim().split(" ");
            for (String word : words) {
                if (word.startsWith("@TableName")) {
                    continue;
                }
                if (WORD_PATTERN.matcher(word).find()) {
                    String newWrod = snakeToCamel(word);
                    Log.log(word + " ===> " + newWrod);
                    l = l.replace(word, newWrod);
                }
            }
            sb.append(l).append("\r\n");
        }


        String absolutePath = file.getAbsolutePath();
        String targetFilePath = absolutePath.replace(sourcePath, targetPath);
        FileWriter writer = new FileWriter(targetFilePath);
        writer.write(sb.toString());
        count++;
    }

    public static String snakeToCamel(String snake) {

        StringBuilder sb = new StringBuilder();
        String[] parts = snake.split("_");
        for (int i = 0; i < parts.length; i++) {
            if (0 == parts[i].length()) {
                continue;
            }
            if (0 == i) {
                sb.append(parts[i]);
            } else {
                char c = parts[i].charAt(0);
                if (c > 96 && c < 123) {
                    sb.append((char) (c - 32)).append(parts[i].substring(1));
                } else {
                    sb.append("_").append(parts[i]);
                }
            }
        }
        return sb.toString();
    }

    private static class JavaFileFilter implements FileFilter {
        @Override
        public boolean accept(File pathname) {
            return pathname.getName().endsWith(FILE_PATTEN);
        }
    }
}
